﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace NetCoreSocket
{
    using HzySocket.WebSocket;
    using HzySocket.WebSocket.Core;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.Extensions.DependencyInjection;
    using Newtonsoft.Json;

    public class WebSocketWork : HzyWebSocketMiddleware<AppSession>
    {
        public WebSocketWork()
        {
            //监听非活跃用户 清除回调
            InactiveCloseCallBack = (_WebSocketMsgModel) => { };
            //连接关闭回调事件
            ConnectCloseCallBack = (_WebSocketMsgModel) => { };

            //发送异常
            SendExceptionCall = (ex) => { };
        }

        public static void RegisterService(IServiceCollection services)
        {
            services.AddTransient<WebSocketWork>();
        }

        public static void Register(IApplicationBuilder _IApplicationBuilder)
        {
            //webScoket
            _IApplicationBuilder.UseWebSockets(new WebSocketOptions()
            {
                ReceiveBufferSize = 1024 * 10,
                KeepAliveInterval = TimeSpan.FromSeconds(60 * 10) //10s
            });
            _IApplicationBuilder.UseMiddleware<WebSocketWork>();
        }

        public override async Task ExecuteCommand(AppSession appSession)
        {
            try
            {
                var dataString = appSession.Data.ToString();
                var data = JsonConvert.DeserializeObject<WebSocketMsgModel>(dataString);
                if (data == null) return;

                // 心跳
                if (data.Key == WebSocketActionEnum.Heartbeat)
                {
                    appSession.LastActiveTime = DateTime.Now;
                    await appSession.SendAsync(new { status = 1, msg = $"{data.UserID} 收到心跳包,当前时间:{DateTime.Now}" });
                }

                if (data.Key == WebSocketActionEnum.Register)
                {
                    appSession.UserID = data.UserID;

                    await appSession.SendAsync(new { status = 1, msg = $"{data.UserID},恭喜您已经注册上线!" });
                }
                else if (data.Key == WebSocketActionEnum.SendToUser) //给别人发消息
                {
                    if (data.ToUserID == null)
                        await SendAllAsync(data.Message);
                    else
                        await SendAsync(w => w.UserID == data.ToUserID, data.Message);
                }
            }
            catch (Exception ex)
            {
                //接收到 非 json 字符串
                await appSession.SendAsync(new
                    { status = 1, msg = $"程序异常:{ex.Message}，接收到您的字符串:{appSession.Data} 请尽量使用 Json 字符串 与服务器交互!" });
            }
        }

        /// <summary>
        /// 根据条件筛选 Session 对象
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public static IEnumerable<AppSession> GetAppSessions(Func<AppSession, bool> predicate)
            => WebSocketSessionContainer<AppSession>.GetAppSessions(predicate);

        /// <summary>
        /// 获取 所有 session 对象
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<AppSession> GetAllAppSessions()
            => WebSocketSessionContainer<AppSession>.GetAllAppSessions();

        /// <summary>
        /// 插入Session 对象
        /// </summary>
        /// <param name="appSession"></param>
        public static void AddAppSession(AppSession appSession)
            => WebSocketSessionContainer<AppSession>.AddAppSession(appSession);

        /// <summary>
        /// 移除Session 对象
        /// </summary>
        /// <param name="predicate"></param>
        public static void RemoveSession(Func<AppSession, bool> predicate)
            => WebSocketSessionContainer<AppSession>.RemoveSession(predicate);

        /// <summary>
        /// 获取 session 连接数
        /// </summary>
        /// <returns></returns>
        public static int GetAppSessionCount()
            => WebSocketSessionContainer<AppSession>.GetAppSessionCount();

        /// <summary>
        /// 检查 session 是否存在
        /// </summary>
        /// <returns></returns>
        public static bool Any(Func<AppSession, bool> predicate)
            => WebSocketSessionContainer<AppSession>.Any(predicate);

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="predicate"></param>
        /// <param name="Data"></param>
        public static async Task SendAsync<T>(Func<AppSession, bool> predicate, T Data)
            => await WebSocketSessionContainer<AppSession>.SendAsync(predicate, Data);

        /// <summary>
        /// 所有连接用户发送消息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="Data"></param>
        public static async Task SendAllAsync<T>(T Data)
            => await WebSocketSessionContainer<AppSession>.SendAllAsync(Data);
    }


    /// <summary>
    /// WebSocket 消息 模型
    /// </summary>
    public class WebSocketMsgModel : WebSocketMessageBase<WebSocketActionEnum>
    {
        public string UserID { get; set; }

        public string ToUserID { get; set; }

        public string Message { get; set; }
    }

    public class AppSession : WebSocketSessionBase
    {
        public string UserID { get; set; }
    }

    public enum WebSocketActionEnum
    {
        // 心跳
        Heartbeat,
        Register,
        SendToUser
    }
}